package settings

import (
	"errors"
	"fmt"
	"github.com/fsnotify/fsnotify"
	"github.com/spf13/viper"
	"gopkg.in/yaml.v3"
	"log"
)

type Config struct {
	*AppConfig   `mapstructure:"app"`
	*LogConfig   `mapstructure:"log"`
	*DBConfig    `mapstructure:"db"`
	*RedisConfig `mapstructure:"redis"`
}

type AppConfig struct {
	Name      string `mapstructure:"name"`
	Mode      string `mapstructure:"mode"`
	Port      uint16 `mapstructure:"port"`
	StartTime string `mapstructure:"startTime"`
	MachineID int64  `mapstructure:"machineID"`
}

type LogConfig struct {
	Level      string `mapstructure:"level"`
	Path       string `mapstructure:"path"`
	MaxSize    uint16 `mapstructure:"maxSize"`
	MaxAge     uint32 `mapstructure:"maxAge"`
	MaxBackups uint32 `mapstructure:"maxBackups"`
	Compress   bool   `mapstructure:"compress"`
}

type DBConfig struct {
	Driver  string `mapstructure:"driver"`
	Dsn     string `mapstructure:"dsn"`
	MaxOpen uint16 `mapstructure:"maxOpen"`
	MaxIdle uint16 `mapstructure:"maxIdle"`
}

type RedisConfig struct {
	Host         string `mapstructure:"host"`
	Password     string `mapstructure:"password"`
	Port         int    `mapstructure:"port"`
	DB           int    `mapstructure:"db"`
	PoolSize     int    `mapstructure:"poolSize"`
	MinIdleConns int    `mapstructure:"minIdleConns"`
}

// 初始化配置信息
func Init(in string) {

	readConf(in)
}

var Conf *Config

func readConf(in string) {
	viper.SetConfigFile(in)
	viper.AddConfigPath(".")
	if err := viper.ReadInConfig(); err != nil {
		panic(errors.New(fmt.Sprintf("read config file %s err:%v\n", in, err)))
	}

	if err := viper.Unmarshal(&Conf); err != nil {
		log.Fatalf("unable to decode into struct, %v", err)
	}

	viper.WatchConfig()
	viper.OnConfigChange(func(in fsnotify.Event) {
		fmt.Printf("config file %s changed \n", in.Name)

		if err := viper.Unmarshal(&Conf); err != nil {
			log.Fatalf("unable to decode into struct, %v", err)
		}
	})

	as := viper.AllSettings()
	bs, _ := yaml.Marshal(as)

	fmt.Printf("config file \n %s \n", string(bs))
}
